package com.huilian.iotbox.admin.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.huilian.iotbox.admin.dao.MerchantDao;
import com.huilian.iotbox.admin.service.MerchantPayCompanyService;
import com.huilian.iotbox.admin.service.MerchantService;
import com.huilian.iotbox.admin.service.MerchantStoreService;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.config.AgencyConfig;
import com.huilian.iotbox.data.config.MiddlewareConfig;
import com.huilian.iotbox.data.dto.MerchantDto;
import com.huilian.iotbox.data.enums.FunctionEnum;
import com.huilian.iotbox.data.enums.MerchantStatusEnum;
import com.huilian.iotbox.data.enums.RequestStatus;
import com.huilian.iotbox.data.exception.ControllerException;
import com.huilian.iotbox.data.po.Merchant;
import com.huilian.iotbox.data.po.PayCompany;
import com.huilian.iotbox.data.utils.HttpUtils;
import com.huilian.iotbox.data.utils.HttpsMain;
import com.huilian.iotbox.data.utils.RsaUtil;
import com.huilian.iotbox.data.vo.MerchantStoreVo;
import com.huilian.iotbox.data.vo.MerchantVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.Serializable;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 谢洛涛
 * @date 2021/6/25 10:03
 */
@Service
@Slf4j
public class MerchantServiceImpl implements MerchantService {
    @Resource
    private MerchantDao merchantDao;
    @Autowired
    private MerchantStoreService merchantStoreService;
    @Autowired
    private AgencyConfig agencyConfig;
    @Resource
    private RedisTemplate<String, Serializable> redisCacheTemplate;
    @Resource
    private MerchantPayCompanyService merchantPayCompanyService;

    @Override
    public List<Merchant> findMerchantList() {
        return merchantDao.findMerchantList();
    }

    @Override
    public MerchantVo findMerchantByMerchantId(String merchantId) {
        return merchantDao.findMerchantByMerchantId(merchantId);
    }

    @Override
    public PageInfo findList(MerchantDto merchantDto) {
        PageHelper.startPage(merchantDto.getPageNum(), merchantDto.getPageSize(), " m.createTime desc");
        List<MerchantVo> list = merchantDao.findList(merchantDto);
        PageInfo pageInfo = new PageInfo(list);
        return pageInfo;
    }

    @Override
    public List<MerchantVo> findAuthenticationStatusById(Integer id) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
        MerchantVo merchantVo = merchantDao.findAuthenticationStatusById(id);
        List<MerchantVo> list=new ArrayList<>();
        Map<String, Object> form = new HashMap<>();
        if (merchantVo.getStatus().equals(MerchantStatusEnum.OFF.getCode()) || merchantVo.getStatus().equals(MerchantStatusEnum.SUCCESS.getCode()) || merchantVo.getStatus().equals(MerchantStatusEnum.RISK.getCode())) {
            form.put("outTradeNo", merchantVo.getOutTradeNo());
            form.put("HlMerchantId", merchantVo.getMerchantId());
            String param = HttpUtils.format(agencyConfig, form, FunctionEnum.MERCHANT_QUERY, merchantVo.getPayCompanyCode());
            String response = HttpsMain.httpsReq(MiddlewareConfig.merchantInfo, param);
            final Map<String, Object> result = HttpUtils.getResultData(response);
            log.info("响应报文result: {}", result);
            // 支付宝微信认证信息
            if (RequestStatus.SUCCESS.getCode().equals(result.get("status")) && RequestStatus.SUCCESS_CODE.getCode().equals(result.get("code"))) {
                Map<String, Object> resMap = (Map<String, Object>) result.get("data");
                Map<String, Object> res = (Map<String, Object>) resMap.get("merchant");
                Map<String, Object> merchantDetail = (Map<String, Object>) res.get("merchantDetail");
                Map<String, Object> merchantBankCard = (Map<String, Object>) res.get("merchantBankCard");
                Map<String, Object> form2 = new HashMap<>();
                form2.put("HlMerchantId", merchantVo.getMerchantId());
                String paramValue = HttpUtils.format(agencyConfig, form2, FunctionEnum.MERCHANT_REGISTER_QUERY, merchantVo.getPayCompanyCode());
                log.info("商户注册查询接口请求报文{}", paramValue);
                String responseValue = HttpsMain.httpsReq(MiddlewareConfig.Merchant + "/queryAuthorizeInfo", paramValue);
                log.info("商户注册查询接口响应报文{}", responseValue);
                if (!RsaUtil.verifyResponseSign(responseValue)) {
                    log.info("验签失败");
                    throw new ControllerException("验签失败");
                }
                JSONObject jsonObject = JSONObject.parseObject(responseValue);
                Map<String, Object> data = (Map<String, Object>) jsonObject.get("data");
                Map<String, Object> merchantData = (Map<String, Object>) data.get("merchant");
                //同步状态值
                Merchant editMerchant = new Merchant();
                editMerchant.setWeChatApplymentState((String) merchantData.get("applymentState"));
                editMerchant.setWeChatAuthorizeState((String) merchantData.get("authorizeState"));
                editMerchant.setAliApplymentState((String) merchantData.get("aliApplymentState"));
                editMerchant.setAliAuthorizeState((String) merchantData.get("aliAuthorizeState"));
                editMerchant.setOutTradeNo(merchantVo.getOutTradeNo());
                merchantDao.updateMerchant(editMerchant);
                String timestampStr = (String) jsonObject.get("timestamp");
                if (timestampStr != null) {
                    Long timestamp = Long.parseLong(timestampStr);
                    Date date = new Date(timestamp);

                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String formattedDate = sdf.format(date);
                    merchantVo.setTimestamp(formattedDate);
                }
                PayCompany payCompany = merchantPayCompanyService.finOnePayCompany(merchantVo.getPayCompanyCode());
                MerchantVo aliMerchantVo=new MerchantVo();
                aliMerchantVo.setRealName((String) merchantBankCard.get("bankCertName"));
                aliMerchantVo.setMerchantName((String) res.get("merchantName"));
                aliMerchantVo.setFailReason((String) merchantData.get("aliFailReason"));
                aliMerchantVo.setCertificationChannels(0);
                if (!ObjectUtils.isEmpty(merchantData.get("smid"))){
                    aliMerchantVo.setMerchantId((String) merchantData.get("smid"));
                    aliMerchantVo.setAliMerchId((String) merchantData.get("smid"));
                    aliMerchantVo.setAliApplymentState((String)merchantData.get("aliApplymentState"));
                    aliMerchantVo.setAliAuthorizeState((String)merchantData.get("aliAuthorizeState"));
                    aliMerchantVo.setAliQrcode((String) merchantData.get("aliQrcode"));
                    aliMerchantVo.setTimestamp(merchantVo.getTimestamp());
                    aliMerchantVo.setStatus(merchantVo.getStatus());
                    //aliApplymentState等于AUDIT_REJECT审核失败,等于CANCELED已测回,AUDIT_FREEZE已冻结,AUDITING审核中并且支付宝没有返回二维码 返回渠道二维码
                    if (ObjectUtils.isEmpty(aliMerchantVo.getAliApplymentState()) || !ObjectUtils.isEmpty(aliMerchantVo.getAliApplymentState()) &&
                            (aliMerchantVo.getAliApplymentState().equals("AUDIT_REJECT") || aliMerchantVo.getAliApplymentState().equals("CANCELED") ||
                                    (aliMerchantVo.getAliApplymentState().equals("AUDIT_FREEZE") || aliMerchantVo.getAliApplymentState().equals("AUDITING")) && ObjectUtils.isEmpty(aliMerchantVo.getAliQrcode()))) {
                        aliMerchantVo.setChannelCode(payCompany.getAlipayChatCertificationCode());
                    }
                }
                list.add(aliMerchantVo);


                MerchantVo weChatMerchantVo=new MerchantVo();
                weChatMerchantVo.setMerchantName((String) res.get("merchantName"));
                weChatMerchantVo.setRealName((String)merchantBankCard.get("bankCertName"));
                weChatMerchantVo.setFailReason((String) merchantData.get("wxFailReason"));
                weChatMerchantVo.setCertificationChannels(1);
                if (!ObjectUtils.isEmpty(merchantData.get("wechatMerchId"))){
                    weChatMerchantVo.setMerchantId((String) merchantData.get("wechatMerchId"));
                    weChatMerchantVo.setWechatMerchId((String) merchantData.get("wechatMerchId"));
                    weChatMerchantVo.setWeChatApplymentState((String) merchantData.get("applymentState"));
                    weChatMerchantVo.setQrcodeData((String) merchantData.get("qrcodeData"));
                    weChatMerchantVo.setWeChatAuthorizeState((String) merchantData.get("authorizeState"));
                    weChatMerchantVo.setStatus(merchantVo.getStatus());
                    weChatMerchantVo.setTimestamp(merchantVo.getTimestamp());
                    //applymentState等于APPLYMENT_STATE_REJECTED审核失败,APPLYMENT_STATE_CANCELED已作废(撤销),APPLYMENT_STATE_FREEZED已冻结,APPLYMENT_STATE_WAITTING_FOR_AUDIT审核中并且微信没有返回二维码   返回渠道二维码
                    if (ObjectUtils.isEmpty(weChatMerchantVo.getWeChatApplymentState()) || !ObjectUtils.isEmpty(weChatMerchantVo.getWeChatApplymentState()) &&
                            (weChatMerchantVo.getWeChatApplymentState().equals("APPLYMENT_STATE_REJECTED") || weChatMerchantVo.getWeChatApplymentState().equals("APPLYMENT_STATE_CANCELED") ||
                                    ((weChatMerchantVo.getWeChatApplymentState().equals("APPLYMENT_STATE_FREEZED") || weChatMerchantVo.getWeChatApplymentState().equals("APPLYMENT_STATE_WAITTING_FOR_AUDIT")) && ObjectUtils.isEmpty(weChatMerchantVo.getQrcodeData())))) {
                        weChatMerchantVo.setChannelCode(payCompany.getWeChatCertificationCode());
                    }
                }
                list.add(weChatMerchantVo);
            }

        }else {
            throw new RuntimeException("商户未开通！");
        }
        return list;
    }

    @Override
    public ServerResponse switchoverPayCompany(MerchantDto merchantDto) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
        // 判断商户订单号是否存
        if (StringUtils.isEmpty(merchantDto.getMerchantId()) || StringUtils.isEmpty(merchantDto.getPayCompanyCode())) {
            return ServerResponse.createByErrorMessage("商户号或支付渠道不存在，请重新操作");
        }
        Map<String, Object> form = new HashMap<>();
        form.put("HlMerchantId", merchantDto.getMerchantId());
        String param = HttpUtils.format(agencyConfig, form, FunctionEnum.SWITCHOVER_PAY_COMPANY, merchantDto.getPayCompanyCode());
        String response = HttpsMain.httpsReq(MiddlewareConfig.switchoverPayCompany, param);
        log.info("请求响应结果{}", response);
        //延签并返回map值
        final Map<String, Object> result = HttpUtils.getResultData(response);
        final String status = (String) result.get("status");
        final String code = (String) result.get("code");
        if (status.equals(RequestStatus.SUCCESS.getCode()) && code.equals(RequestStatus.SUCCESS_CODE.getCode())) {
            Merchant merchant = new Merchant();
            merchant.setPayCompanyCode(merchantDto.getPayCompanyCode());
            merchant.setOutTradeNo(merchantDto.getOutTradeNo());
            merchantDao.updateMerchant(merchant);
            // 根据商户号查询已绑定的商户
            List<MerchantStoreVo> MerchantStoreVoList = merchantStoreService.findAllMerchantStoreByMerchantId(merchantDto.getMerchantId());
            for (MerchantStoreVo merchantStoreVo : MerchantStoreVoList) {
                redisCacheTemplate.delete(String.format(RedisKey.MERCHANT_STORE, merchantStoreVo.getId()));
            }

            return ServerResponse.createBySuccess((String) result.get("msg"));
        } else {
            return ServerResponse.createByErrorMessage((String) result.get("msg"));
        }
    }
}
